﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using aoprinter.Model;

namespace aoprinter.Draw
{
    /// <summary>
    /// set relative block at fit position
    /// </summary>
    class BlockRegion
    {
        private List<RectangleF> _regions;
        private SizeF _parentSize = SizeF.Empty;
        private List<float> _lstLocationY;
        private int _index;

        public BlockRegion(SizeF parentSize)
        {
            _regions = new List<RectangleF>();
            _parentSize = parentSize;
            _lstLocationY = new List<float>();
        }

        public PointF GetFitPosition(PointF location, SizeF size, float interval)
        {
            PointF pointAt = PointF.Empty;
            if (location.X > 0)
            {
                if (!IfIntersectY(ref pointAt, size, interval))
                {
                    _regions.Add(new RectangleF(pointAt, size));
                    return pointAt;
                }
            }
            else
            {
                _index = 0;
                CreateHeightArray();
                if (!IfIntersectX(ref pointAt, size, interval))
                {
                    _regions.Add(new RectangleF(pointAt, size));
                    return pointAt;
                }
            }
            return PointF.Empty;
        }

        private void CreateHeightArray()
        {
            _lstLocationY.Clear();
            for (int i = 0; i < _regions.Count; i++)
            {
                if (!_lstLocationY.Contains(_regions[i].Location.Y + _regions[i].Height))
                {
                    _lstLocationY.Add(_regions[i].Location.Y + _regions[i].Height);
                }
            }
            _lstLocationY.Sort();
        }

        private RectangleF GetIntersectRect(PointF location, SizeF size)
        {
            if (size.IsEmpty)
            {
                return RectangleF.Empty;
            }
            for (int i = 0; i < _regions.Count; i++)
            {
                if (Rectangle.Truncate(_regions[i]).IntersectsWith(new Rectangle(Point.Truncate(location), Size.Truncate(size))))
                {
                    return _regions[i];
                }
            }
            return RectangleF.Empty;
        }

        private bool IfIntersectX(ref PointF location, SizeF size, float interval)
        {
            RectangleF rectF = GetIntersectRect(location, size);
            if (rectF.IsEmpty) return false;
            location = new PointF(rectF.Location.X + rectF.Width + interval, location.Y);
            if (location.X + size.Width > _parentSize.Width)
            {
                if (_lstLocationY.Count > _index)
                {
                    location = new PointF(0, _lstLocationY[_index] + interval);
                    _index++;
                }
            }
            return IfIntersectX(ref location, size, interval);
        }

        private bool IfIntersectY(ref PointF location, SizeF size, float interval)
        {
            RectangleF rectF = GetIntersectRect(location, size);
            if (rectF.IsEmpty) return false;
            location = new PointF(0, rectF.Location.Y + rectF.Height + interval);
            return IfIntersectY(ref location, size, interval);
        }

        public SizeF ParentSize
        {
            get
            {
                CreateHeightArray();
                if (_lstLocationY.Count > 0)
                {
                    _parentSize = new SizeF(_parentSize.Width, _lstLocationY[_lstLocationY.Count - 1]);
                }
                else
                {
                    _parentSize = new SizeF(_parentSize.Width, 0);
                }
                return _parentSize;
            }
        }
    }
}
